package com.zonski.jbots.engine;

import com.zonski.jbots.engine.Engine;

/**
 * Class for running the engine class and performing repaints
 */
public abstract class AbstractEngineRunner 
{
    private Engine engine;
    private EngineRunnable runnable;

    private Thread thread;

    private long ticksPerUpdate = 1000/20;

    public AbstractEngineRunner(Engine engine)
    {
        this.engine = engine;
        this.runnable = new EngineRunnable();
    }

    public long getTicksPerUpdate()
    {
        return this.ticksPerUpdate;
    }

    public void setTicksPerUpdate(long ticksPerUpdate)
    {
        this.ticksPerUpdate = ticksPerUpdate;
    }

    public void start()
    {
        if(this.thread == null)
        {
            this.runnable = new EngineRunnable();
            this.thread = new Thread(runnable);
            //this.thread.setPriority(Thread.MAX_PRIORITY);
            this.thread.start();
        }
    }

    public void stop()
    {
        if(this.thread != null)
        {
            this.engine.getDevice().stopAll();
            this.runnable.running = false;
            this.runnable = null;
            this.thread = null;
        }
    }

    public boolean isRunning()
    {
        return this.thread != null;
    }

    public boolean checkIntro()
    {
        // called when introduction is being shown, usually will lead into playing the game
        return true;
    }

    protected abstract void onUpdate();

    private class EngineRunnable implements Runnable
    {
        public boolean running = true;

        public void run()
        {
            //long totalWaits = 0;
            //int totalUpdates = 0;
            //long totalLost = 0;
            while(running)
            {
                long time = System.currentTimeMillis();
                try
                {
                    AbstractEngineRunner.this.engine.update();
                }catch(Exception ex){
                    ex.printStackTrace();
                }
                AbstractEngineRunner.this.onUpdate();
                long lost = System.currentTimeMillis() - time;
                long tosleep = AbstractEngineRunner.this.ticksPerUpdate - lost;
                //totalLost += lost;
                //totalUpdates++;
                if(tosleep > 0)
                {
                    //totalWaits += tosleep;
                    try
                    {
                        Thread.sleep(tosleep);
                    }catch(Exception ex){
                        //running = false;
                        ex.printStackTrace();

                    }
                }
            }
            //System.out.println("average wait time "+(totalWaits/totalUpdates));
            //System.out.println("average lost time "+(totalLost/totalUpdates));
        }
    }
}
